#include <bits/stdc++.h>
#include <semaphore.h>
#include <pthread.h>

using namespace std;

//#define DEBUG_USE_ONLY

#ifndef DEBUG_USE_ONLY
#include <QDebug>
#endif

#define nssym 		256		// 单字符个数
#define txmax 		100		// 符号表容量
#define nmax 		14		// 数字的最大位数
#define norw 		17		// 保留字个数
#define symnum 		42		// 单词符号个数

#define errnum 		30		// 出错原因数
#define maxerr 		30     	// 允许的最多错误数

#define amax 		2048	// 地址上界
#define levmax 		3      	// 最大允许过程嵌套声明层数
#define cxmax 		200     // 最多的虚拟机代码数
#define stacksize 	500 	// 运行时数据栈元素最多为500个

#define fctnum 		7		// 虚拟机代码指令个数

#define memcpy(a, b)		memcpy(a, b, sizeof(bool) * symnum)
#define memzro(a)			memset(a, 0, sizeof(bool) * symnum)

extern sem_t readdata;      // 是否需要输入
extern sem_t dataready;     // 数据已经读好了
extern int p;               // 指令指针
extern int isComplete;      // 标记是否解释执行完成
extern int indata;          // read得到的值

/* 符号：3，22个符号，17个保留字(norw)，去修改.h中的symnum和init() */
enum symbol {
    nul,        ident,      number,
	
	plussym,    minussym, 
    times,      slash,      assign,     lparen,     rparen,
    lbrace,     rbrace,     colon,      comma,      semicolon,
    lss,        gtr,        excla,      percent,	geq,
	leq,		neq,        eql,        incre,      decre,

	ifsym,		elsesym,    forsym,     whilesym,   dosym,      
	intsym,		readsym,    writesym,   constsym,	xorsym,
	oddsym,		boolsym,	truesym,	falsesym,	andsym,
	orsym,		notsym,
};

/* 符号表的类型 */
enum object {
	constint,
	constbool,
	integer,
    boolean,
};

/* 符号表结构 */
struct tablestruct{
	string name;			// 名字
	enum object kind;		// 类型
	int val;				// constant
	int level;				// variable
	int adr;				// 地址，仅const不使用
	int size;				// 需要分配的数据区空间，仅procedure使用
};

/* 虚拟机代码指令 */
enum fct{
	lit, opr, lod, sto, ini, jmp, jpc
};

/* 虚拟机代码结构 */
struct instruction{
	enum fct f;			// 虚拟机代码指令
	int l;				// 引用层与声明层的层次差
	int a;				// 根据f的不同而不同
};

/* 编译 */
void compile(string *, string *, string *, string *);

/* 解释执行 */
void interpret(string *);
void interpret_by_step(string *, string *);

void init();            // 初始化可识别单词符号表
void error(int);        // 出错处理

/* 词法分析 */
void getch();           // 读入下一个字符
void getsym();          // 读入下一个符号

/* 语法分析 */
void enter(enum object, int * ptx, int lev, int * pdx);
int position(string id, int tx);

/* 出错处理 */
void test(bool *, bool *, int);
int inset(int, bool *);
int addset(bool *, bool *, bool *, int);
int subset(bool *, bool *, bool *, int);
int mulset(bool *, bool *, bool *, int);

/* 目标代码生成及解释执行 */
void gen(enum fct, int, int);
int base(int, int *, int);
void listinstr();
void listtable(int);
void liststack(int *, int);

/* 递归下降子程序 */
/**
 * 编译程序主体
 * @param tx	符号表当前尾指针
 * @param fsys	当前模块的后继符号集合
 */
void program			(int lev, int * ptx);
/**
 * 声明列表处理
 */
void declaration_list	(bool * fsys, int * ptx, int lev, int * pdx);
/**
 * 声明行处理
 */
void declaration_stat	(int * ptx, int lev, int * pdx);
/**
 * 语句列表处理
 */
void statement_list		(bool * fsys, int * ptx, int lev);
/**
 * 语句处理
 */
void statement			(bool * fsys, int * ptx, int lev);
/**
 * if语句处理
 * 1. IF-ELSE ***************
 * 		T(expression)
 * 		jpc 0, L1		// no, goto else statement
 * 		T(statement)	// if statement
 * 		jmp 0, Lend
 * L1:	T(statement)	// else statement
 * Lend:
 * 2. IF ********************
 * 		T(expression)
 * 		jpc 0, L1
 * 		T(statement)
 * L1:
 */
void if_stat			(bool * fsys, int * ptx, int lev);
/**
 * while语句处理
 * L1:	T(expression)
 * 		jpc 0, L2
 * 		T(statement)
 * 		jmp 0, L1
 * L2:
 */
void while_stat			(bool * fsys, int * ptx, int lev);
/**
 * write语句处理
 * 		T(expression)
 * 		opr 0, 20			// write
 * 		opr 0, 21			// 换行
 */
void write_stat			(bool * fsys, int * ptx, int lev);
/**
 * read语句处理：read ID;
 * 		opr 0, 22			// read
 * 		sto lev-level, adr	// store
 */
void read_stat			(bool * fsys, int * ptx, int lev);
/**
 * 复合语句处理
 * 		T(statement_list)
 */
void compound_stat		(bool * fsys, int * ptx, int lev);
/**
 * 表达式语句处理
 * 		T(expression)
 * 		opr 0, 23		// pop
 */
void expression_stat	(bool * fsys, int * ptx, int lev);
/**
 * 表达式处理
 * 1. ID = <bool_expr> ******
 * 		T(bool_expr)
 * 		sto lev-level, adr
 * 		lod ID				// 留ID的值在栈顶
 * 2. <bool_expr> ***********
 * 		T(bool_expr)
 */
void expression			(bool * fsys, int * ptx, int lev);
/**
 * 布尔表达式处理
 * 1. 预取
 * 1.1. ID { relop [not] <bool_value> }
 * 		lod ID / lit ID
 * 		{ T(bool_value)
 * 		  [ opr 0, 19 ]		// not
 * 		  opr 0, relop  }
 * 1.2. <additive_expr> [ relop <additive_expr> ]
 * 		T(additive_expr) with prei
 * 		[ T(additive_expr)
 * 		  opr 0, relop     ]
 * 2. 无预取
 * 2.1. odd expression
 * 		T(expression)
 * 		opr 0, 6			// odd
 * 2.2. [not] <bool_value> { relop [not] <bool_value> }
 * 		T(bool_value)
 * 		[ opr 0, 19 ]
 * 		{ T(bool_value)
 * 		  [ opr 0, 19 ]
 *        opr 0, relop  }
 * 2.3. <additive_expr> [ relop <additive_expr> ]
 * 		T(additive_expr)
 * 		[ T(additive_expr) 
 * 		  opr 0, relop     ]
 */
void bool_expr			(bool * fsys, int * ptx, int lev, int prei = 0);
/**
 * 加法表达式处理：<term1> [ relop <term2> ]
 * 		T(term1)
 * 		[ T(term2)
 * 		  gen(opr 0, relop) ]
 */
void additive_expr		(bool * fsys, int * ptx, int lev, int prei = 0);
/**
 * 项处理：<factor1> [ relop <factor2> ]
 * 		T(factor1)
 * 		[ T(factor2)
 * 		  gen(opr 0, relop) ]
 */
void term				(bool * fsys, int * ptx, int lev, int prei = 0);
/**
 * 因子处理
 * 1. 预取 ID [++/--]
 * 		lod ID / lit ID.val
 * 		[ lod ID		// 压入ID的旧值
 *        lit 0, 1
 * 		  opr 0, 2/3
 * 		  sto ID     ]
 * 2. 无预取
 * 2.1. ID [++/--]
 * 2.2. NUM
 * 		lit 0, NUM
 * 2.3. ( expression )
 * 		T(expression)
 */
void factor				(bool * fsys, int * ptx, int lev, int prei = 0);
/**
 * 布尔值处理：ID/true/false
 * 		lod ID / lit true|false
 */
void bool_value			(bool * fsys, int * ptx, int lev);
/**
 * for循环处理：for ( [ <expression1> ] ; [ <bool_expr> ] ; [ <expression2> ] ) <statement>
 * 		[ T(expression1) ]
 * L1:	[ T(bool_expr) ]
 * 		jpc 0, Lend		// 假出口
 * 		jmp 0, L3		// 真出口
 * L2:	[ T(expression2) ]
 * 		jmp 0, L1
 * L3:	T(statement)
 * 		jmp 0, L2
 * Lend:
 */
void for_stat			(bool * fsys, int * ptx, int lev);
/**
 * do-while循环处理：do <statement> while ( <expression> );
 * L1:	T(statement)
 * 		T(expression)
 * 		jpc 0, Lend
 * 		jmp 0, L1
 * Lend:
 */
void dowhile_stat		(bool * fsys, int * ptx, int lev);
